package com.sc.nft.dao;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sc.nft.entity.DigitalCollection;
import com.sc.nft.entity.EquityProps;
import com.sc.nft.entity.SecondCollectionConfig;
import com.sc.nft.entity.dto.BrandConfigVO;
import com.sc.nft.entity.dto.FreeMarketPageDTO;
import com.sc.nft.entity.dto.SecondCollectionConfigDTO;
import com.sc.nft.entity.dto.SecondCollectionDTO;
import com.sc.nft.entity.vo.BrandConfigAdminVO;
import com.sc.nft.entity.vo.UserWithCollectionSimpleVO;
import com.sc.nft.enums.MarketTypeEnum;
import com.sc.nft.mapper.SecondCollectionConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 二级藏品配置表(sc_second_collection_config)数据DAO
 *
 * @author kancy
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2022-10-03 16:53:14
 */
@Slf4j
@Repository
public class SecondCollectionConfigDao extends ServiceImpl<SecondCollectionConfigMapper, SecondCollectionConfig> {

    @Resource
    private SecondCollectionDao secondCollectionDao;

    @Resource
    private SecondOrderEsDao secondOrderEsDao;

    @Resource
    private DigitalCollectionDao digitalCollectionDao;

    @Resource
    private EquityPropsDao equityPropsDao;

    public SecondCollectionConfig getByCollectionId(Long collectionId) {
        LambdaQueryWrapper<SecondCollectionConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondCollectionConfig::getCollectionId, collectionId);
        return getOne(wrapper);
    }

    public SecondCollectionConfig getByCollectionIdAndStatus(Long collectionId) {
        LambdaQueryWrapper<SecondCollectionConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondCollectionConfig::getCollectionId, collectionId);
        wrapper.eq(SecondCollectionConfig::getStatus, Boolean.TRUE);
        return getOne(wrapper);
    }

    public SecondCollectionConfig getByCollectionIdAndMarketType(Long collectionId, MarketTypeEnum marketType) {
        LambdaQueryWrapper<SecondCollectionConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondCollectionConfig::getCollectionId, collectionId);
        wrapper.eq(SecondCollectionConfig::getMarketType, marketType);
        wrapper.eq(SecondCollectionConfig::getStatus, Boolean.TRUE);
        return getOne(wrapper);
    }

    public Page<SecondCollectionDTO> pageSecond(String firstTitle, int pageNo, int pageSize, Integer type, Boolean newOrOld) {
        // 涉及 sc_second_order 关联查询，解决 sc_second_order 表异构带来的关联查询问题
        Page<SecondCollectionDTO> page = baseMapper.pageSecond(new Page<>(pageNo, pageSize), firstTitle, type, newOrOld);

        if (!CollectionUtils.isEmpty(page.getRecords())) {
            fillSecondOrderInfo(page.getRecords());
        }

        return page;
    }

    /**
     * 使用接口填充 sales_count, prevent_hoard_income 字段，解除 sc_second_order 关联查询
     */
    private void fillSecondOrderInfo(List<SecondCollectionDTO> records) {
        List<Long> collectionIds = records.stream()
                .filter(Objects::nonNull)
                .map(SecondCollectionDTO::getCollectionId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collectionIds)) {
            return;
        }

        // (SELECT COUNT(*) FROM sc_second_order WHERE collection_id = scc.collection_id AND is_delete = 0 AND STATUS = 2) AS sales_count
        Map<Long, Long> salesCountMap = secondOrderEsDao.groupSalesCount(collectionIds);

        // (SELECT IFNULL(SUM(prevent_hoard), 0) FROM sc_second_order WHERE collection_id = scc.collection_id) AS prevent_hoard_income
        Map<Long, BigDecimal> preventHoardIncomeMap = secondOrderEsDao.groupPreventHoardIncome(collectionIds);

        List<Long> wantBuyHoldCollectionIdList = records.stream()
                .filter(Objects::nonNull)
                .map(SecondCollectionDTO::getWantBuyHoldCollectionId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        List<DigitalCollection> digitalCollectionList = CollectionUtil.isNotEmpty(wantBuyHoldCollectionIdList) ? digitalCollectionDao.listByIds(wantBuyHoldCollectionIdList) : Lists.newArrayList();
        Map<Long, DigitalCollection> digitalCollectionMap = CollectionUtil.isNotEmpty(digitalCollectionList) ? digitalCollectionList.stream().collect(Collectors.toMap(DigitalCollection::getId, Function.identity())) : Maps.newHashMap();

        List<Long> wantBuyConsumePropIdList = records.stream()
                .filter(Objects::nonNull)
                .map(SecondCollectionDTO::getWantBuyConsumePropId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        List<EquityProps> equityPropsList = CollectionUtil.isNotEmpty(wantBuyConsumePropIdList) ? equityPropsDao.listByIds(wantBuyConsumePropIdList) : Lists.newArrayList();
        Map<Long, EquityProps> equityPropsMap = CollectionUtil.isNotEmpty(equityPropsList) ? equityPropsList.stream().collect(Collectors.toMap(EquityProps::getId, Function.identity())) : Maps.newHashMap();

        records.stream()
                .filter(Objects::nonNull)
                .filter(sc -> Objects.nonNull(sc.getCollectionId()))
                .forEach(sc -> {
                    sc.setSalesCount(salesCountMap.get(sc.getCollectionId()));
                    sc.setPreventHoardIncome(preventHoardIncomeMap.get(sc.getCollectionId()));
                    if (Objects.nonNull(sc.getWantBuyHoldCollectionId())) {
                        DigitalCollection digitalCollection = digitalCollectionMap.get(sc.getWantBuyHoldCollectionId());
                        if (Objects.nonNull(digitalCollection)) {
                            sc.setWantBuyHoldCollectionName(digitalCollection.getFirstTitle());
                        }
                    }
                    if (Objects.nonNull(sc.getWantBuyConsumePropId())) {
                        EquityProps equityProps = equityPropsMap.get(sc.getWantBuyConsumePropId());
                        if (Objects.nonNull(equityProps)) {
                            sc.setWantBuyConsumePropName(equityProps.getFirstTitle());
                        }
                    }
                });
    }

    public Page<BrandConfigVO> brandConfigPage(String firstTitle, Integer showLevel, Long userCreatorId, Integer sortType, Integer pageNo, Integer pageSize) {
        // 备注：涉及 sc_second_collection 表查询，内置条件 status=1，不必修改
        Page<BrandConfigVO> brandConfigVOPage = baseMapper.brandConfigPage(new Page<>(pageNo, pageSize), firstTitle, showLevel, userCreatorId, sortType);
        List<BrandConfigVO> records = brandConfigVOPage.getRecords();
        for (BrandConfigVO record : records) {
            BigDecimal antihoardRatio = record.getAntihoardRatio();
            BigDecimal cumulativeIncrease = record.getCumulativeIncrease();
            BigDecimal upRatio = record.getUpRatio();
            record.setUpRatioString(upRatio.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_DOWN).toPlainString() + "%");
            record.setCumulativeIncreaseString(cumulativeIncrease.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_DOWN).toPlainString() + "%");
            record.setAntihoardRatioString(antihoardRatio.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_DOWN).toPlainString() + "%");
        }
        return brandConfigVOPage;
    }

    /**
     * 后端市值账号,用来扫货收货使用.其他地方禁止使用.
     *
     * @return
     */
    public List<BrandConfigAdminVO> brandConfigList() {
        // 备注：涉及 sc_second_collection 表查询，内置条件 status=1，不必修改
        List<BrandConfigAdminVO> brandConfigVOPage = baseMapper.brandConfigList();
        return brandConfigVOPage;
    }

    /**
     * 后端市值账号,用来扫货收货使用.其他地方禁止使用.
     *
     * @return
     */
    public List<BrandConfigAdminVO> freemarketConfigList(String firstTitle, Long userId) {
        List<BrandConfigAdminVO> freemarketConfigPageVo = baseMapper.freemarketConfigList(firstTitle, userId);
        return freemarketConfigPageVo;
    }

    public Page<SecondCollectionConfigDTO> freeMarketPage(String firstTitle, Integer showLevel, Long userCreatorId, Integer sortType, Integer pageNo, Integer pageSize) {
        // 备注：涉及 sc_second_collection 表查询，内置条件 status=1，不必修改
        return baseMapper.freeMarketPage(new Page<>(pageNo, pageSize), firstTitle, showLevel, userCreatorId, sortType);
    }

    public List<SecondCollectionConfig> freeMarketReference() {
        QueryWrapper<SecondCollectionConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("market_type", MarketTypeEnum.FREE_MARKET);
        return list(queryWrapper);
    }

    public List<SecondCollectionConfig> getListByStatusAndMarketType(MarketTypeEnum type) {
        LambdaQueryWrapper<SecondCollectionConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondCollectionConfig::getMarketType, type);
        wrapper.eq(SecondCollectionConfig::getStatus, Boolean.TRUE);
        return list(wrapper);
    }

    public List<Long> getCollectionIdsByType(MarketTypeEnum type) {
        LambdaQueryWrapper<SecondCollectionConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SecondCollectionConfig::getCollectionId);
        wrapper.eq(SecondCollectionConfig::getMarketType, type);
        wrapper.eq(SecondCollectionConfig::getStatus, Boolean.TRUE);
        return listObjs(wrapper, x -> (Long) x);
    }

    public Boolean saveFloatingPrice(SecondCollectionConfig secondCollectionConfig, Long id) {
        UpdateWrapper<SecondCollectionConfig> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("floating_price", secondCollectionConfig.getFloatingPrice());
//        updateWrapper.set("min_price", secondCollectionConfig.getMinPrice());
//        updateWrapper.set("max_price", secondCollectionConfig.getMaxPrice());
        updateWrapper.eq("id", id);
        return update(updateWrapper);
    }

    public Page<SecondCollectionConfigDTO> freeMarketPagev3_7(String firstTitle, Integer showLevel, Long userCreatorId, Integer sortType, Integer pageNo, Integer pageSize, Integer status) {
        // 备注：涉及 sc_second_collection 表查询，内置条件 status=1，不必修改
        Page<Object> objectPage = new Page<>(pageNo, pageSize);
        objectPage.setSearchCount(false);
        objectPage.setTotal(baseMapper.freeMarketPagev3_7Count(firstTitle, showLevel, userCreatorId, sortType, status));
        Page<SecondCollectionConfigDTO> page = baseMapper.freeMarketPagev3_7(new Page<>(pageNo, pageSize), firstTitle, showLevel, userCreatorId, sortType, status);
        for (SecondCollectionConfigDTO record : page.getRecords()) {
            record.setMinPrice(secondCollectionDao.getMinPriceByCollectionId(record.getCollectionId()));
            record.setSalesCount(secondCollectionDao.getSalesCountByCollectionId(record.getCollectionId()));
        }
        return page;
    }


    public List<UserWithCollectionSimpleVO> getCollectionIdList(Integer marketType) {
        return baseMapper.getCollectionIdList(marketType);
    }

    public SecondCollectionConfig getByPanelIdOne(Long panelId) {
        return lambdaQuery().eq(SecondCollectionConfig::getShareProfitPanelId, panelId).last("limit 1").one();
    }


    public IPage<SecondCollectionConfigDTO> freeMarketPagev5_4(FreeMarketPageDTO freeMarketPageVO) {
        // 备注：涉及 sc_second_collection 表查询，内置条件 status=1，不必修改
        Page<Object> objectPage = new Page<>(freeMarketPageVO.getPageNo(), freeMarketPageVO.getPageSize() > 20 ? 20 : freeMarketPageVO.getPageSize());
        objectPage.setSearchCount(false);
        objectPage.setTotal(baseMapper.freeMarketPagev5_4Count(freeMarketPageVO));

        return baseMapper.freeMarketPagev5_4(objectPage, freeMarketPageVO);
    }


}